home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 4 / Assassins 4 (1999)(Weird Science).iso / misc / omega / source / aux2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-02  |  30.5 KB  |  1,199 lines

  1. /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
  2. /* aux2.c */
  3. /* some functions called by ocom.c, also see aux1.c and aux3.c*/ 
  4. /* This is a real grab bag file. It contains functions used by
  5.    aux1.c and omega.c, as well as elsewhere. It is mainly here so aux1.c
  6.    and aux3.c are not huge */
  7.  
  8. #include "glob.h"
  9.  
  10. /* Player stats like str, agi, etc give modifications to various abilities
  11.    chances to do things, etc. Positive is good, negative bad. */
  12. int statmod(stat)
  13. int stat;
  14. {
  15.   return((stat-10)/2);
  16. }
  17.  
  18.  
  19. /* effects of hitting */
  20. void p_hit (m,dmg,dtype)
  21. struct monster *m;
  22. int dmg;
  23. int dtype;
  24. {
  25.   int dmult;
  26.  
  27.   /* chance for critical hit..., 3/10 */
  28.   switch (random_range(10)) {  
  29.     case 0:
  30.     if (random_range(100) < Player.level) {
  31.       strcpy(Str3,"You annihilate ");
  32.       dmult = 1000;
  33.     }
  34.     else {
  35.       strcpy(Str3,"You blast "); 
  36.       dmult=5; 
  37.     }
  38.     break;
  39.     case 1:
  40.     case 2: 
  41.     strcpy(Str3,"You smash "); 
  42.     dmult=2; break;
  43.  
  44.     default: 
  45.     dmult=1;
  46.     if (random_range(10)) strcpy(Str3,"You hit ");
  47.     else switch(random_range(4)) {
  48.     case 0: strcpy(Str3,"You damage "); break;
  49.     case 1: strcpy(Str3,"You inflict bodily harm on "); break;
  50.     case 2: strcpy(Str3,"You injure "); break;
  51.     case 3: strcpy(Str3,"You molest "); break;
  52.     }
  53.     break;
  54.   } 
  55.   if (Lunarity == 1) dmult = dmult * 2;
  56.   else if (Lunarity == -1) dmult = dmult / 2;
  57.   if (m->uniqueness == COMMON) strcat(Str3,"the ");
  58.   strcat(Str3,m->monstring);
  59.   strcat(Str3,". ");
  60.   if (Verbosity != TERSE) mprint(Str3);
  61.   else mprint("You hit it.");
  62.   m_damage(m,dmult * random_range(dmg),dtype);
  63.   if ((Verbosity != TERSE) && (random_range(10)==3) && (m->hp > 0))
  64.     mprint("It laughs at the injury and fights on!");
  65. }
  66.  
  67. /* and effects of missing */
  68. void player_miss(m,dtype)
  69. struct monster *m;
  70. int dtype;
  71. {
  72.   if (random_range(30)==1) /* fumble 1 in 30 */
  73.     p_fumble(dtype);
  74.   else {
  75.     if (Verbosity != TERSE) {
  76.       if (random_range(10))
  77.     strcpy(Str3,"You miss ");
  78.       else switch(random_range(4)) {
  79.       case 0: strcpy(Str3,"You flail lamely at "); break;
  80.       case 1: strcpy(Str3,"You only amuse "); break;
  81.       case 2: strcpy(Str3,"You fail to even come close to "); break;
  82.       case 3: strcpy(Str3,"You totally avoid contact with "); break;
  83.       }    
  84.       if (m->uniqueness == COMMON) strcat(Str3,"the ");
  85.       strcat(Str3,m->monstring);
  86.       strcat(Str3,". ");
  87.       mprint(Str3);
  88.     }
  89.     else mprint("You missed it.");
  90.   }  
  91. }
  92.  
  93. /* oh nooooo, a fumble.... */
  94. void p_fumble(dtype)
  95. int dtype;
  96. {
  97.   mprint("Ooops! You fumbled....");
  98.   switch(random_range(10)) {
  99.     case 0:
  100.     case 1:
  101.     case 2:
  102.     case 3: 
  103.     case 4: 
  104.     case 5: drop_weapon(); break;
  105.     case 6:
  106.     case 7:
  107.     case 8: break_weapon(); break;
  108.     case 9: mprint("Oh No! You hit yourself!");
  109.         p_damage(Player.dmg,dtype,"stupidity");
  110.         break;
  111.   }
  112. }        
  113.  
  114. /* try to drop a weapon (from fumbling) */
  115. void drop_weapon()
  116. {
  117.   if (Player.possessions[O_WEAPON_HAND] != NULL) {
  118.     strcpy(Str1,"You dropped your ");
  119.     strcat(Str1,Player.possessions[O_WEAPON_HAND]->objstr);
  120.     mprint(Str1);
  121.     morewait();
  122.     p_drop_at(Player.x,Player.y,1,Player.possessions[O_WEAPON_HAND]);
  123.     conform_lost_objects(1,Player.possessions[O_WEAPON_HAND]);
  124.   }
  125.   else mprint("You feel fortunate.");
  126. }
  127.  
  128.  
  129. /* try to break a weapon (from fumbling) */
  130. void break_weapon()
  131. {
  132.   if (Player.possessions[O_WEAPON_HAND] != NULL) {
  133.     strcpy(Str1,"Your ");
  134.     strcat(Str1,itemid(Player.possessions[O_WEAPON_HAND]));
  135.     strcat(Str1," vibrates in your hand....");
  136.     mprint(Str1);
  137.     (void) damage_item(Player.possessions[O_WEAPON_HAND]);
  138.     morewait();
  139.   }
  140. }
  141.  
  142.  
  143. /* hooray */
  144. void p_win()
  145. {
  146.   morewait();
  147.   clearmsg();
  148.   print1("You won!");
  149.   morewait();
  150.   display_win();
  151.   endgraf();
  152.   exit(0);
  153. }
  154.  
  155.  
  156. /* handle a h,j,k,l, etc., to change x and y by dx and dy */
  157. /* for targeting in dungeon */
  158. void movecursor(x,y,dx,dy)
  159. int *x,*y;
  160. int dx,dy;
  161. {
  162.   if (inbounds(*x+dx,*y+dy)) {
  163.     *x += dx;
  164.     *y += dy;
  165.     screencheck(*y);
  166.   }
  167.   omshowcursor(*x,*y);
  168. }
  169.  
  170.  
  171. /* is Player immune to damage type dtype */
  172. int p_immune(dtype)
  173. int dtype;
  174. {
  175.   return(Player.immunity[dtype]>0);
  176. }
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183. /* deal with each possible stati -- values are per move */
  184. /* this function is executed every move */
  185. /* A value over 1000 indicates a permanent effect */
  186. void minute_status_check()
  187. {
  188.   int i;
  189.  
  190.   if (Player.status[HASTED]>0) {
  191.     if (Player.status[HASTED] < 1000) {
  192.       Player.status[HASTED]--;
  193.       if (Player.status[HASTED]==0) {
  194.     mprint("The world speeds up.");
  195.     calc_melee();
  196.       }
  197.     }
  198.   }
  199.  
  200.  
  201.   if (Player.status[POISONED]>0) {
  202.     Player.status[POISONED]--;
  203.     p_damage(3,POISON,"poison");
  204.     if (Player.status[POISONED] == 0) {
  205.       showflags();
  206.       mprint("You feel better now.");
  207.     }
  208.   }
  209.  
  210.  
  211.   if (Player.immunity[UNSTOPPABLE]>0) {
  212.     for(i=0;i<NUMIMMUNITIES;i++)
  213.     Player.immunity[i]--;
  214.     if (Player.immunity[UNSTOPPABLE]==1)
  215.       mprint("You feel vincible again.");
  216.   }
  217.  
  218.  
  219.   if (Player.status[IMMOBILE]>0) {
  220.     Player.status[IMMOBILE]--;
  221.     if (Player.status[IMMOBILE] == 0) 
  222.       mprint("You can move again.");
  223.   }
  224.  
  225.  
  226.   if (Player.status[SLEPT]>0) {
  227.     Player.status[SLEPT]--;
  228.     if (Player.status[SLEPT] == 0) {
  229.       mprint("You woke up.");
  230.     }
  231.   }
  232.  
  233.   if (Player.status[REGENERATING]>0) {
  234.     if ((Player.hp < Player.maxhp) && (Player.mana > 0)){
  235.       Player.hp++;
  236.       Player.mana--;
  237.       dataprint();
  238.     }
  239.     if (Player.status[REGENERATING] < 1000) {
  240.       Player.status[REGENERATING]--;
  241.       if (Player.status[REGENERATING] == 0) {
  242.     mprint("You feel less homeostatic.");
  243.       }
  244.     }
  245.   }
  246.  
  247.   if (Player.status[SLOWED]>0) {
  248.     if (Player.status[SLOWED] < 1000) {
  249.       Player.status[SLOWED]--;
  250.       if (Player.status[SLOWED] == 0) {
  251.     mprint("You feel quicker now.");
  252.     calc_melee();
  253.       }
  254.     }
  255.   }
  256.  
  257.   if (Player.status[RETURNING]>0) {
  258.     Player.status[RETURNING]--;
  259.     if (Player.status[RETURNING] == 10)
  260.       mprint("Your return spell slowly hums towards activation...");
  261.     else if (Player.status[RETURNING] == 8)
  262.       mprint("There is an electric tension in the air!");
  263.     else if (Player.status[RETURNING] == 5)
  264.       mprint("A vortex of mana begins to form around you!");
  265.     else if (Player.status[RETURNING] == 1)
  266.       mprint("Your surroundings start to warp and fade!");
  267.     if (Player.status[RETURNING] == 0)
  268.       level_return();
  269.   }
  270.   
  271.   if (Player.status[AFRAID]>0) {
  272.     if (Player.status[AFRAID] < 1000) {
  273.       Player.status[AFRAID]--;
  274.       if (Player.status[AFRAID] == 0) {
  275.     mprint("You feel bolder now.");
  276.       }
  277.     }
  278.   }
  279.   
  280. }
  281.  
  282.  
  283.  
  284. /* effect of gamma ray radiation... */
  285. void moon_check()
  286. {
  287.   /* 24 day lunar cycle */
  288.   Phase = (Phase+1)%24;
  289.   phaseprint();
  290.   Lunarity = 0;
  291.   if (((Player.patron == DRUID) && ((Phase/2 == 3) || (Phase/2 == 9))) ||
  292.       ((Player.alignment > 10) && (Phase/2 == 6)) ||
  293.       ((Player.alignment < -10) && (Phase/2 == 0))) {
  294.     mprint("As the moon rises you feel unusually vital!");
  295.     Lunarity = 1;
  296.   }
  297.   else
  298.   if (((Player.patron == DRUID) && ((Phase/2 == 0) || (Phase/2 == 6))) ||
  299.       ((Player.alignment > 10) && (Phase/2 == 0)) ||
  300.       ((Player.alignment < -10) && (Phase/2 == 6))) {
  301.     mprint("The rise of the moon tokens a strange enervation!");
  302.     Lunarity = -1;
  303.   }
  304.  
  305. }
  306.  
  307.  
  308.  
  309. /* check 1/hour for torch to burn out if used */
  310. void torch_check()
  311. {
  312.   int i;
  313.   for(i=O_READY_HAND;i<=O_WEAPON_HAND;i++) {
  314.     if (Player.possessions[i]!=NULL)
  315.       if ((Player.possessions[i]->id == THINGID+8) && /*torch */
  316.       (Player.possessions[i]->aux > 0)) {
  317.     Player.possessions[i]->aux--;
  318.     if (Player.possessions[i]->aux==0) {
  319.       mprint("Your torch goes out!!!");
  320.       conform_unused_object(Player.possessions[i]);
  321.       if (Player.possessions[i]->number > 1) {
  322.         Player.possessions[i]->number--;
  323.         Player.possessions[i]->aux = 6;
  324.       }
  325.       else {
  326.         Player.possessions[i]->usef = I_NO_OP;
  327.         Player.possessions[i]->cursestr =
  328.           Player.possessions[i]->truename =
  329.         Player.possessions[i]->objstr = "burnt-out torch";
  330.       }
  331.     }
  332.       }
  333.   }
  334. }
  335.  
  336.  
  337.  
  338. /* values are in multiples of ten minutes */
  339. /* values over 1000 indicate a permanent effect */
  340. void tenminute_status_check()
  341. {
  342.   if ((Player.status[SHADOWFORM]>0) && (Player.status[SHADOWFORM]<1000)) {
  343.     Player.status[SHADOWFORM]--;
  344.     if (Player.status[SHADOWFORM] == 0) {
  345.       Player.immunity[NORMAL_DAMAGE]--;
  346.       Player.immunity[ACID]--;
  347.       Player.immunity[THEFT]--;
  348.       Player.immunity[INFECTION]--;
  349.       mprint("You feel less shadowy now.");
  350.     }
  351.   }
  352.  
  353.   if ((Player.status[ILLUMINATION]>0) && (Player.status[ILLUMINATION]<1000)) {
  354.     Player.status[ILLUMINATION]--;
  355.     if (Player.status[ILLUMINATION] == 0) {
  356.       mprint("Your light goes out!");
  357.     }
  358.   }
  359.  
  360.  
  361.   if ((Player.status[VULNERABLE]>0) && (Player.status[VULNERABLE]<1000)){
  362.     Player.status[VULNERABLE]--;
  363.     if (Player.status[VULNERABLE] == 0)
  364.       mprint("You feel less endangered.");
  365.   }
  366.  
  367.  
  368.   if ((Player.status[DEFLECTION]>0) && (Player.status[DEFLECTION]<1000)){
  369.     Player.status[DEFLECTION]--;
  370.     if (Player.status[DEFLECTION] == 0)
  371.       mprint("You feel less well defended.");
  372.   }
  373.  
  374.   if ((Player.status[ACCURATE]>0) && (Player.status[ACCURACY]<1000)){
  375.     Player.status[ACCURATE]--;
  376.     if (Player.status[ACCURATE] == 0) {
  377.       calc_melee();
  378.       mprint("The bulls' eyes go away.");
  379.     }
  380.   }
  381.   if ((Player.status[HERO]>0) && (Player.status[HERO]<1000)){
  382.     Player.status[HERO]--;
  383.     if (Player.status[HERO] == 0) {
  384.       calc_melee();
  385.       mprint("You feel less than super.");
  386.     }
  387.   }
  388.  
  389.   if ((Player.status[LEVITATING]>0) && (Player.status[LEVITATING]<1000)){
  390.     Player.status[LEVITATING]--;
  391.     if (Player.status[LEVITATING] == 0)
  392.       mprint("You're no longer walking on air.");
  393.   }
  394.  
  395.   if (Player.status[DISEASED]>0) {
  396.     Player.status[DISEASED]--;
  397.     if (Player.status[DISEASED] == 0) {
  398.       showflags();
  399.       mprint("You feel better now.");
  400.     }
  401.   }
  402.  
  403.  
  404.   if ((Player.status[INVISIBLE] > 0) && (Player.status[INVISIBLE]<1000)){
  405.     Player.status[INVISIBLE]--;
  406.     if (Player.status[INVISIBLE] == 0)
  407.       mprint("You feel more opaque now.");
  408.   }
  409.  
  410.   if ((Player.status[BLINDED]>0) && (Player.status[BLINDED]<1000)) {
  411.     Player.status[BLINDED]--;
  412.     if (Player.status[BLINDED] == 0) 
  413.       mprint("You can see again.");
  414.   }
  415.  
  416.   if ((Player.status[TRUESIGHT]>0) && (Player.status[TRUESIGHT]<1000)) {
  417.     Player.status[TRUESIGHT]--;
  418.     if (Player.status[TRUESIGHT] == 0) 
  419.       mprint("You feel less keen now.");
  420.   }
  421.  
  422.   if ((Player.status[BERSERK]>0) && (Player.status[BERSERK]<1000)) {
  423.     Player.status[BERSERK]--;
  424.     if (Player.status[BERSERK] == 0) 
  425.       mprint("You stop foaming at the mouth.");
  426.   }
  427.  
  428.   if ((Player.status[ALERT]>0) && (Player.status[ALERT] < 1000)) {
  429.     Player.status[ALERT]--;
  430.     if (Player.status[ALERT] == 0) 
  431.       mprint("You feel less alert now.");
  432.   }
  433.  
  434.   if ((Player.status[BREATHING]>0) && (Player.status[BREATHING] < 1000)) {
  435.     Player.status[BREATHING]--;
  436.     if (Player.status[BREATHING] == 0) 
  437.       mprint("You feel somewhat congested."); 
  438.   }
  439.  
  440.   if ((Player.status[DISPLACED]>0) && (Player.status[DISPLACED] < 1000)) {
  441.     Player.status[DISPLACED]--;
  442.     if (Player.status[DISPLACED]==0) 
  443.       mprint("You feel a sense of position.");
  444.   }
  445.   timeprint();
  446.   dataprint();
  447. }
  448.  
  449.  
  450.  
  451. /* Increase in level at appropriate experience gain */
  452. void gain_level()
  453. {
  454.   int gained=FALSE;
  455.   if (gamestatusp(SUPPRESS_PRINTING))
  456.     return;
  457.   while (expval(Player.level+1) <= Player.xp) {
  458.     if (!gained)
  459.       morewait();
  460.     gained = TRUE;
  461.     Player.level++;
  462.     print1("You have attained a new experience level!");
  463.     print2("You are now ");
  464.     nprint2(getarticle(levelname(Player.level)));
  465.     nprint2(levelname(Player.level));
  466.     Player.maxhp += random_range(Player.con)+1;
  467.     Player.mana = Player.maxmana = calcmana();
  468.     morewait();
  469.   }
  470.   if (gained) clearmsg();
  471.   calc_melee();
  472. }
  473.  
  474. /* experience requirements */
  475. long expval(plevel)
  476. int plevel;
  477. {
  478.   switch(plevel) {
  479.     case 0:return(0L);
  480.     case 1:return(20L);
  481.     case 2:return(50L);
  482.     case 3:return(200L);
  483.     case 4:return(500L);
  484.     case 5:return(1000L);
  485.     case 6:return(2000L);
  486.     case 7:return(3000L);
  487.     case 8:return(5000L);
  488.     case 9:return(7000L);
  489.     case 10:return(10000L);
  490.     default:return((plevel-9) * 10000L);
  491.   }
  492. }
  493.  
  494. /* If an item is unidentified, it isn't worth much to those who would buy it */
  495. long item_value(item)
  496. pob item;
  497. {
  498.   if (item->known == 0) {
  499.     if (item->objchar == THING) return(1);
  500.     else return(true_item_value(item) / 10);
  501.   }
  502.   else if (item->known == 1) {
  503.     if (item->objchar == THING) return(item->basevalue);
  504.     else return(item->basevalue / 2);
  505.   }
  506.   else return(true_item_value(item));
  507. }
  508.  
  509.  
  510. /* figures value based on item base-value, charge, plus, and blessing */
  511. long true_item_value(item)
  512. pob item;
  513. {
  514.  long value = item->basevalue;
  515.   
  516.   if (item->objchar == THING) return(item->basevalue);
  517.   else {
  518.     if (item->objchar == STICK) value += value*item->charge/20;
  519.     if (item->plus > -1) value += value*item->plus/4;
  520.     else value /= -item->plus;
  521.     if (item->blessing > 0) value *= 2;
  522.     return((long) value);
  523.   }
  524. }
  525.  
  526. /* kill off player if he isn't got the "breathing" status */
  527. void p_drown()
  528. {
  529.   int attempts = 3, i;
  530.  
  531.   if (Player.status[BREATHING] > 0)
  532.     mprint("Your breathing is unaffected!");
  533.   else while (Player.possessions[O_ARMOR] ||
  534.       Player.itemweight > ((int) (Player.maxweight / 2))) {
  535.     menuclear();
  536.     switch (attempts--) {
  537.       case 3: print3("You try to hold your breath..."); break;
  538.       case 2: print3("You try to hold your breath... You choke..."); break;
  539.       case 1: print3("You try to hold your breath... You choke... Your lungs fill..."); break;
  540.       case 0: p_death("drowning");
  541.     }
  542.     morewait();
  543.     menuprint("a: Drop an item.\n");
  544.     menuprint("b: Bash an item.\n");
  545.     menuprint("c: Drop your whole pack.\n");
  546.     showmenu();
  547.     switch(menugetc()) {
  548.       case 'a':
  549.     drop();
  550.     if (Level->site[Player.x][Player.y].p_locf == L_WATER && Level->site[Player.x][Player.y].things)
  551.     {
  552.         mprint("It sinks without a trace.");
  553.         free_objlist(Level->site[Player.x][Player.y].things);
  554.         Level->site[Player.x][Player.y].things = NULL;
  555.     }
  556.     break;
  557.       case 'b':
  558.     bash_item();
  559.     break;
  560.       case 'c':
  561.     setgamestatus(SUPPRESS_PRINTING);
  562.     for(i=0;i<MAXPACK;i++) {
  563.       if (Player.pack[i] != NULL)
  564.         if (Level->site[Player.x][Player.y].p_locf != L_WATER)
  565.           p_drop_at(Player.x,Player.y,Player.pack[i]->number,Player.pack[i]);
  566.         free((char *) Player.pack[i]);
  567.       Player.pack[i] = NULL;
  568.     }
  569.     if (Level->site[Player.x][Player.y].p_locf == L_WATER)
  570.       mprint("It sinks without a trace.");
  571.     Player.packptr = 0;
  572.     resetgamestatus(SUPPRESS_PRINTING);
  573.     calc_melee();
  574.     break;
  575.     }
  576.   }
  577.   show_screen();
  578.   return;
  579. }
  580.  
  581.  
  582. /* the effect of some weapon on monster m, with dmgmod a bonus to damage */
  583. void weapon_use(dmgmod,weapon,m)
  584. int dmgmod;
  585. pob weapon;
  586. struct monster *m;
  587. {
  588.   int aux = (weapon==NULL ? -2 : weapon->aux); /* bare hands */
  589.   switch(aux) {
  590.     case -2: weapon_bare_hands(dmgmod,m); break;
  591.     default:
  592.     case I_NO_OP: weapon_normal_hit(dmgmod,weapon,m); break;
  593.     case I_ACIDWHIP: weapon_acidwhip(dmgmod,weapon,m); break;
  594.     case I_TANGLE: weapon_tangle(dmgmod,weapon,m); break;
  595.     case I_ARROW: weapon_arrow(dmgmod,weapon,m); break;
  596.     case I_BOLT: weapon_bolt(dmgmod,weapon,m); break;
  597.     case I_DEMONBLADE: weapon_demonblade(dmgmod,weapon,m); break;
  598.     case I_LIGHTSABRE: weapon_lightsabre(dmgmod,weapon,m); break;
  599.     case I_MACE_DISRUPT: weapon_mace_disrupt(dmgmod,weapon,m); break;
  600.     case I_VORPAL: weapon_vorpal(dmgmod,weapon,m); break;
  601.     case I_DESECRATE: weapon_desecrate(dmgmod,weapon,m); break;
  602.     case I_FIRESTAR: weapon_firestar(dmgmod,weapon,m); break;
  603.     case I_DEFEND: weapon_defend(dmgmod,weapon,m); break;
  604.     case I_VICTRIX: weapon_victrix(dmgmod,weapon,m); break;
  605.     case I_SCYTHE: weapon_scythe(dmgmod,weapon,m); break;
  606.   }
  607. }
  608.  
  609.  
  610. /* for printing actions in printactions above */
  611. char *actionlocstr(dir)
  612. char dir;
  613. {
  614.   switch(dir) {
  615.   case 'L': strcpy(Str3,"low."); break;
  616.   case 'C': strcpy(Str3,"center."); break;
  617.   case 'H': strcpy(Str3,"high."); break;
  618.   default: strcpy(Str3,"wildly."); break;
  619.   }
  620.   return(Str3);
  621. }
  622.  
  623.  
  624. /* execute player combat actions versus monster m */
  625. void tacplayer(m)
  626. struct monster *m;
  627. {
  628.   int i=0;
  629.  
  630.   while (i < strlen(Player.meleestr)) {
  631.     if (m->hp > 0) {
  632.       switch(Player.meleestr[i]) {
  633.       case 't': case 'T':
  634.     if (Player.possessions[O_WEAPON_HAND] == NULL) 
  635.       strcpy(Str1,"You punch ");
  636.     else strcpy(Str1,"You thrust ");
  637.     strcat(Str1,actionlocstr(Player.meleestr[i+1]));
  638.     if (Verbosity == VERBOSE) mprint(Str1);
  639.     if (player_hit(2*statmod(Player.dex),Player.meleestr[i+1],m))
  640.       weapon_use(0,Player.possessions[O_WEAPON_HAND],m);
  641.     else player_miss(m,NORMAL_DAMAGE);
  642.     break;
  643.       case 'c': case 'C':
  644.     if (Player.possessions[O_WEAPON_HAND] == NULL) 
  645.       strcpy(Str1,"You punch ");
  646.     else if (Player.possessions[O_WEAPON_HAND]->type == CUTTING) 
  647.       strcpy(Str1,"You cut ");
  648.     else if (Player.possessions[O_WEAPON_HAND]->type == STRIKING) 
  649.       strcpy(Str1,"You strike ");
  650.     else strcpy(Str1,"You attack ");
  651.     strcat(Str1,actionlocstr(Player.meleestr[i+1]));
  652.     if (Verbosity == VERBOSE) mprint(Str1);
  653.     if (player_hit(0,Player.meleestr[i+1],m))
  654.       weapon_use(2*statmod(Player.str),
  655.              Player.possessions[O_WEAPON_HAND],
  656.              m);
  657.     else player_miss(m,NORMAL_DAMAGE);
  658.     break;
  659.       case 'l': case 'L':
  660.     strcpy(Str1,"You lunge ");
  661.     strcat(Str1,actionlocstr(Player.meleestr[i+1]));
  662.     if (Verbosity == VERBOSE) mprint(Str1);
  663.     if (player_hit(Player.level+Player.dex,Player.meleestr[i+1],m))
  664.       weapon_use(Player.level,Player.possessions[O_WEAPON_HAND],m);
  665.     else player_miss(m,NORMAL_DAMAGE);
  666.     break;
  667.       }
  668.     }    
  669.     i+=2;
  670.   }
  671. }
  672.  
  673.  
  674.  
  675.  
  676. /* checks to see if player hits with hitmod vs. monster m at location hitloc */
  677. int player_hit(hitmod,hitloc,m)
  678. int hitmod;
  679. char hitloc;
  680. struct monster *m;
  681. {
  682.   int i=0,blocks=FALSE,goodblocks=0,hit;
  683.   if (m->hp < 1) {
  684.     mprint("Unfortunately, your opponent is already dead!");
  685.     return(FALSE);
  686.   }
  687.   else {
  688.     if (hitloc == 'X') hitloc = random_loc();
  689.  
  690.     transcribe_monster_actions(m);
  691.  
  692.     while (i<strlen(m->meleestr)) {
  693.       if ((m->meleestr[i] == 'B') || (m->meleestr[i] == 'R')) {
  694.     blocks = TRUE;
  695.     if (hitloc == m->meleestr[i+1])
  696.       goodblocks++;
  697.       }
  698.       i+=2;
  699.     }
  700.  
  701.     if (! blocks) goodblocks = -1;
  702.     hit = hitp(Player.hit+hitmod,m->ac+goodblocks*10);
  703.     if ((! hit) && (goodblocks > 0)) {
  704.       if (m->uniqueness == COMMON) {
  705.     strcpy(Str1,"The ");
  706.     strcat(Str1,m->monstring);
  707.       }
  708.       else strcpy(Str1,m->monstring);
  709.       strcat(Str1," blocks it!");
  710.       if (Verbosity == VERBOSE) mprint(Str1);
  711.     }
  712.     return(hit);
  713.   }
  714. }
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722. /* This function is used to undo all items temporarily, should
  723. always be used in pairs with on being TRUE and FALSE, and may cause
  724. anomalous stats and item-usage if used indiscriminately */
  725.  
  726. void toggle_item_use(on)
  727. int on;
  728. {
  729.   static int used[MAXITEMS];
  730.   int i;
  731.   setgamestatus(SUPPRESS_PRINTING);
  732.   if (on) 
  733.     for(i=0;i<MAXITEMS;i++) {
  734.       used[i] = FALSE;
  735.       if (Player.possessions[i] != NULL) {
  736.     if ((used[i] = Player.possessions[i]->used) == TRUE) {
  737.       Player.possessions[i]->used = FALSE;
  738.       item_use(Player.possessions[i]);
  739.     }
  740.       }
  741.     }
  742.   else {
  743.     for(i=1;i<MAXITEMS;i++) 
  744.       if (used[i]) {
  745.     Player.possessions[i]->used = TRUE;
  746.     item_use(Player.possessions[i]);
  747.       }
  748.     calc_melee();
  749.     showflags();
  750.     dataprint();
  751.     timeprint();
  752.   }
  753.   resetgamestatus(SUPPRESS_PRINTING);
  754. }
  755.  
  756.  
  757. void enter_site(site)
  758. short site;
  759. {
  760.   switch(site) {
  761.   case CITY: change_environment(E_CITY); break;
  762.   case VILLAGE: change_environment(E_VILLAGE); break;
  763.   case CAVES: change_environment(E_CAVES); break;
  764.   case CASTLE: change_environment(E_CASTLE); break;
  765.   case VOLCANO: change_environment(E_VOLCANO); break;
  766.   case TEMPLE: change_environment(E_TEMPLE); break;
  767.   case DRAGONLAIR: change_environment(E_DLAIR); break;
  768.   case STARPEAK: change_environment(E_STARPEAK); break;
  769.   case MAGIC_ISLE: change_environment(E_MAGIC_ISLE); break;
  770.   default:print3("There's nothing to enter here!"); break;
  771.   }
  772. }
  773.  
  774.  
  775.  
  776. /* Switches context dungeon/countryside/city, etc */
  777. void change_environment(new_environment)
  778. char new_environment;
  779. {
  780.   int i,emerging = FALSE;
  781.  
  782.   Player.sx = -1; Player.sy = -1; /* reset sanctuary if there was one */
  783.   resetgamestatus(LOST);    /* in case the player gets lost _on_ a site */
  784.  
  785.   resetgamestatus(FAST_MOVE);
  786.  
  787.   Last_Environment = Current_Environment;
  788.   if (Last_Environment == E_COUNTRYSIDE) {
  789.     LastCountryLocX = Player.x;
  790.     LastCountryLocY = Player.y;
  791.   }
  792.   if (((Last_Environment == E_CITY) ||
  793.        (Last_Environment == E_VILLAGE)) &&
  794.       ((new_environment == E_MANSION) ||
  795.        (new_environment == E_HOUSE) ||
  796.        (new_environment == E_HOVEL) ||
  797.        (new_environment == E_SEWERS) ||
  798.        (new_environment == E_ARENA))) {
  799.     LastTownLocX = Player.x;
  800.     LastTownLocY = Player.y;
  801.   }
  802.   else if (((Last_Environment == E_MANSION) ||
  803.         (Last_Environment == E_HOUSE) ||
  804.         (Last_Environment == E_HOVEL) ||
  805.         (Last_Environment == E_SEWERS) ||
  806.         (Last_Environment == E_ARENA)) &&
  807.        ((new_environment == E_CITY) ||
  808.         (new_environment == E_VILLAGE))) {
  809.     Player.x = LastTownLocX;
  810.     Player.y = LastTownLocY;
  811.     emerging = TRUE;
  812.   }
  813.  
  814.   Current_Environment = new_environment;
  815.   switch(new_environment) {
  816.   case E_ARENA:
  817.     LENGTH = 16;
  818.     WIDTH = 64;
  819.     Player.x = 5;
  820.     Player.y = 7;
  821.     setgamestatus(ARENA_MODE);
  822.     load_arena();
  823.     ScreenOffset = 0;
  824.     show_screen();
  825.     break;
  826.   case E_ABYSS:
  827.     LENGTH = 16;
  828.     WIDTH = 64;
  829.     Player.x = 32;
  830.     Player.y = 15;
  831.     load_abyss();
  832.     abyss_file();
  833.     lose_all_items();
  834.     ScreenOffset = 0;
  835.     show_screen();
  836.     break;
  837.   case E_CIRCLE:
  838.     LENGTH = 16;
  839.     WIDTH = 64;
  840.     Player.x = 32;
  841.     Player.y = 14;
  842.     load_circle(TRUE);
  843.     if (Objects[ARTIFACTID+21].uniqueness == UNIQUE_TAKEN) {
  844.       print1("A bemused voice says:");
  845.       print2("'Why are you here? You already have the Star Gem!'");
  846.       morewait();
  847.     }
  848.     else if (Player.rank[CIRCLE] > 0) {
  849.       print1("You hear the voice of the Prime Sorceror:");
  850.       print2("'Congratulations on your attainment of the Circle's Demesne.'");
  851.       morewait();
  852.       print1("For the honor of the Circle, you may take the Star Gem");
  853.       print2("and destroy it on the acme of Star Peak.");
  854.       morewait();
  855.       print1("Beware the foul LawBringer who resides there...");
  856.       print2("By the way, some of the members of the Circle seem to");
  857.       morewait();
  858.       print1("have become a bit jealous of your success --");
  859.       print2("I'd watch out for them too if I were you.");
  860.       morewait();
  861.     }
  862.     else if (Player.alignment > 0) {
  863.       print1("A mysterious ghostly image materializes in front of you.");
  864.       print2("It speaks: 'Greetings, fellow abider in Law. I am called");
  865.       morewait();
  866.       print1("The LawBringer. If you wish to advance our cause, obtain");
  867.       print2("the mystic Star Gem and return it to me on Star Peak.");
  868.       morewait();
  869.       print1("Beware the power of the evil Circle of Sorcerors and the");
  870.       print2("forces of Chaos which guard the gem.'");
  871.       morewait();
  872.       print1("The strange form fades slowly.");
  873.       morewait();
  874.     }
  875.     ScreenOffset = 0;
  876.     show_screen();
  877.     break;
  878.   case E_COURT:
  879.     WIDTH = 64;
  880.     LENGTH = 24;
  881.     Player.x = 32;
  882.     Player.y = 2;
  883.     LastCountryLocX = 6;
  884.     LastCountryLocY = 1;
  885.     load_court(TRUE);
  886.     ScreenOffset = 0;
  887.     show_screen();
  888.     break;
  889.   case E_MANSION:
  890.     WIDTH = 64;
  891.     LENGTH = 16;
  892.     load_house(E_MANSION, TRUE);
  893.     Player.y = 8;
  894.     Player.x = 2;
  895.     ScreenOffset = 0;
  896.     show_screen();
  897.     break;
  898.   case E_HOUSE:
  899.     WIDTH = 64;
  900.     LENGTH = 16;
  901.     load_house(E_HOUSE, TRUE);
  902.     Player.y = 13;
  903.     Player.x = 2;
  904.     ScreenOffset = 0;
  905.     show_screen();
  906.     break;
  907.   case E_HOVEL:
  908.     WIDTH = 64;
  909.     LENGTH = 16;
  910.     load_house(E_HOVEL, TRUE);
  911.     Player.y = 9;
  912.     Player.x = 2;
  913.     ScreenOffset = 0;
  914.     show_screen();
  915.     break;
  916.   case E_DLAIR:
  917.     WIDTH = 64;
  918.     LENGTH = 16;
  919.     Player.y = 9;
  920.     Player.x = 2;
  921.     load_dlair(gamestatusp(KILLED_DRAGONLORD), TRUE);
  922.     ScreenOffset = 0;
  923.     show_screen();
  924.     break;
  925.   case E_STARPEAK:
  926.     WIDTH = 64;
  927.     LENGTH = 16;
  928.     Player.y = 9;
  929.     Player.x = 2;
  930.     load_speak(gamestatusp(KILLED_LAWBRINGER), TRUE);
  931.     ScreenOffset = 0;
  932.     show_screen();
  933.     break;
  934.   case E_MAGIC_ISLE:
  935.     WIDTH = 64;
  936.     LENGTH = 16;
  937.     Player.y = 14;
  938.     Player.x = 62;
  939.     load_misle(gamestatusp(KILLED_EATER), TRUE);
  940.     ScreenOffset = 0;
  941.     show_screen();
  942.     break;
  943.   case E_TEMPLE:
  944.     WIDTH = 64;
  945.     LENGTH = 16;
  946.     load_temple(Country[Player.x][Player.y].aux, TRUE);
  947.     Player.y = 15;
  948.     Player.x = 32;
  949.     ScreenOffset = 0;
  950.     show_screen();
  951.     break;
  952.   case E_CITY:
  953.     WIDTH = 64;
  954.     LENGTH = 64;
  955.     if (emerging) {
  956.       print1("You emerge onto the street.");
  957.       emerging = FALSE;
  958.     }
  959.     else {
  960.       print1("You pass through the massive gates of Rampart, the city.");
  961.       Player.x = 62;
  962.       Player.y = 21;
  963.     }
  964.     if (City == NULL) load_city(TRUE);
  965. #ifdef SAVE_LEVELS
  966.     else
  967.         msdos_changelevel(Level,new_environment,0);
  968. #endif
  969.     Level = City;
  970.     ScreenOffset = Player.y - (ScreenLength/2);
  971.     show_screen();
  972.     break;
  973.   case E_VILLAGE:
  974.     WIDTH = 64;
  975.     LENGTH = 16;
  976.     if (!emerging) {
  977.       /* different villages per different locations */
  978.       switch(Country[Player.x][Player.y].aux) {
  979.       case 1:
  980.     Player.x = 0;
  981.     Player.y = 6;
  982.     Villagenum = 1;
  983.     break;
  984.       default: 
  985.     print3("Very strange, a nonexistent village.");
  986.       case 2:
  987.     Player.x = 39;
  988.     Player.y = 15;
  989.     Villagenum = 2;
  990.     break;
  991.       case 3:
  992.     Player.x = 63;
  993.     Player.y = 8;
  994.     Villagenum = 3;
  995.     break;
  996.       case 4: 
  997.     Player.x = 32;
  998.     Player.y = 15;
  999.     Villagenum = 4;
  1000.     break;
  1001.       case 5: 
  1002.     Player.x = 2;
  1003.     Player.y = 8;
  1004.     Villagenum = 5;
  1005.     break;
  1006.       case 6: 
  1007.     Player.x = 2;
  1008.     Player.y = 2;
  1009.     Villagenum = 6;
  1010.     break;
  1011.       }
  1012.     }
  1013.     if ((! emerging) || (TempLevel == NULL)) load_village(Villagenum, TRUE);
  1014.     else if (TempLevel->environment != E_VILLAGE) load_village(Villagenum, TRUE);
  1015. #ifndef SAVE_LEVELS
  1016.     else Level = TempLevel;
  1017. #else
  1018.     else {
  1019.       msdos_changelevel(Level,new_environment,0);
  1020.       Level = TempLevel;
  1021.       }
  1022. #endif
  1023.     if (emerging) {
  1024.       print1("You emerge onto the street.");
  1025.       emerging = FALSE;
  1026.     }
  1027.     else
  1028.       print1("You enter a small rural village.");
  1029.     ScreenOffset = 0;
  1030.     show_screen();
  1031.     break;
  1032.   case E_CAVES:
  1033.     WIDTH = 64;
  1034.     LENGTH = 64;
  1035.     print1("You enter a dark cleft in a hillside;");
  1036.     print2("You note signs of recent passage in the dirt nearby.");
  1037.     if (gamestatusp(MOUNTED)) {
  1038.       morewait();
  1039.       print1("Seeing as you might not be coming back, you feel compelled");
  1040.       print2("to let your horse go, rather than keep him hobbled outside.");
  1041.       resetgamestatus(MOUNTED);
  1042.       calc_melee();
  1043.     }
  1044.     MaxDungeonLevels = CAVELEVELS;
  1045.     if (Current_Dungeon != E_CAVES) {
  1046. #ifdef SAVE_LEVELS
  1047.     msdos_changelevel(Level,0,-1);
  1048. #endif
  1049.       free_dungeon();
  1050.       Dungeon = NULL;
  1051.       Level = NULL;
  1052.       Current_Dungeon = E_CAVES;
  1053.     }
  1054.     change_level(0,1,FALSE);
  1055.     break;
  1056.   case E_VOLCANO:
  1057.     WIDTH = 64;
  1058.     LENGTH = 64;
  1059.     print1("You pass down through the glowing crater.");
  1060.     if (gamestatusp(MOUNTED)) {
  1061.       morewait();
  1062.       print1("Seeing as you might not be coming back, you feel compelled");
  1063.       print2("to let your horse go, rather than keep him hobbled outside.");
  1064.       resetgamestatus(MOUNTED);
  1065.       calc_melee();
  1066.     }
  1067.     MaxDungeonLevels = VOLCANOLEVELS;
  1068.     if (Current_Dungeon != E_VOLCANO) {
  1069. #ifdef SAVE_LEVELS
  1070.     msdos_changelevel(Level,0,-1);
  1071. #endif
  1072.       free_dungeon();
  1073.       Dungeon = NULL;
  1074.       Level = NULL;
  1075.       Current_Dungeon = E_VOLCANO;
  1076.     }
  1077.     change_level(0,1,FALSE);
  1078.     break;
  1079.   case E_ASTRAL:
  1080.     WIDTH = 64;
  1081.     LENGTH = 64;
  1082.     print1("You are in a weird flickery maze.");
  1083.     if (gamestatusp(MOUNTED)) {
  1084.       print2("Your horse doesn't seem to have made it....");
  1085.       resetgamestatus(MOUNTED);
  1086.       calc_melee();
  1087.     }
  1088.     MaxDungeonLevels = ASTRALLEVELS;
  1089.     if (Current_Dungeon != E_ASTRAL) {
  1090. #ifdef SAVE_LEVELS
  1091.     msdos_changelevel(Level,0,-1);
  1092. #endif
  1093.       free_dungeon();
  1094.       Dungeon = NULL;
  1095.       Level = NULL;
  1096.       Current_Dungeon = E_ASTRAL;
  1097.     }
  1098.     change_level(0,1,FALSE);
  1099.     break;
  1100.   case E_CASTLE:
  1101.     WIDTH = 64;
  1102.     LENGTH = 64;
  1103.     print1("You cross the drawbridge. Strange forms move beneath the water.");
  1104.     if (gamestatusp(MOUNTED)) {
  1105.       morewait();
  1106.       print1("Seeing as you might not be coming back, you feel compelled");
  1107.       print2("to let your horse go, rather than keep him hobbled outside.");
  1108.       resetgamestatus(MOUNTED);
  1109.     }
  1110.     MaxDungeonLevels = CASTLELEVELS;
  1111.     if (Current_Dungeon != E_CASTLE) {
  1112. #ifdef SAVE_LEVELS
  1113.     msdos_changelevel(Level,0,-1);
  1114. #endif
  1115.       free_dungeon();
  1116.       Dungeon = NULL;
  1117.       Level = NULL;
  1118.       Current_Dungeon = E_CASTLE;
  1119.     }
  1120.     change_level(0,1,FALSE);
  1121.     break;
  1122.   case E_SEWERS:
  1123.     WIDTH = 64;
  1124.     LENGTH = 64;
  1125.     print1("You pry open a manhole and descend into the sewers below.");
  1126.     if (gamestatusp(MOUNTED)) {
  1127.       print2("You horse waits patiently outside the sewer entrance....");
  1128.       dismount_steed();
  1129.     }
  1130.     MaxDungeonLevels = SEWERLEVELS;
  1131.     if (Current_Dungeon != E_SEWERS) {
  1132. #ifdef SAVE_LEVELS
  1133.     msdos_changelevel(Level,0,-1);
  1134. #endif
  1135.       free_dungeon();
  1136.       Dungeon = NULL;
  1137.       Level = NULL;
  1138.       Current_Dungeon = E_SEWERS;
  1139.     }
  1140.     change_level(0,1,FALSE);
  1141.     break;
  1142.   case E_COUNTRYSIDE:
  1143.     WIDTH = 64;
  1144.     LENGTH = 64;
  1145.     print1("You return to the fresh air of the open countryside.");
  1146.     if (Last_Environment == E_CITY) {
  1147.       Player.x = 27;
  1148.       Player.y = 19;
  1149.     }
  1150.     else {
  1151.       Player.x = LastCountryLocX;
  1152.       Player.y = LastCountryLocY;
  1153.     }
  1154.     for(i=0;i<9;i++)
  1155.       c_set(Player.x+Dirs[0][i], Player.y+Dirs[1][i], SEEN);
  1156.     ScreenOffset = Player.y - (ScreenLength/2);
  1157.     show_screen();
  1158.     break;
  1159.   case E_TACTICAL_MAP:
  1160.     WIDTH = 64;
  1161.     LENGTH = 16;
  1162.     print1("You are now on the tactical screen; exit off any side to leave");
  1163.     make_country_screen(Country[Player.x][Player.y].current_terrain_type);
  1164.     make_country_monsters(Country[Player.x][Player.y].current_terrain_type);
  1165.     Player.x = WIDTH/2;
  1166.     Player.y = LENGTH/2;
  1167.     while (Level->site[Player.x][Player.y].locchar == WATER) {
  1168.       if (Player.y < LENGTH/2 + 5)
  1169.     Player.y++;
  1170.       else if (Player.x > WIDTH/2 - 10) {
  1171.     Player.x--;
  1172.     Player.y = LENGTH/2 - 5;
  1173.       }
  1174.       else {
  1175.     Level->site[Player.x][Player.y].locchar =
  1176.       Level->site[Player.x][Player.y].showchar = FLOOR;
  1177.     Level->site[Player.x][Player.y].p_locf = L_NO_OP;
  1178.       }
  1179.     }
  1180.     ScreenOffset = 0;
  1181.     show_screen();
  1182.     break;
  1183.   case E_NEVER_NEVER_LAND: default:
  1184.     print1("There must be some mistake. You don't look like Peter Pan.");
  1185.     print2("(But here you are in Never-Never Land)");
  1186.     ScreenOffset = Player.y - (ScreenLength/2);
  1187.     show_screen();
  1188.     break;
  1189.   }
  1190.   setlastxy(Player.x, Player.y);
  1191.   if (Current_Environment != E_COUNTRYSIDE)
  1192.     showroom(Level->site[Player.x][Player.y].roomnumber);
  1193.   else
  1194.     terrain_check(FALSE);
  1195. }
  1196.  
  1197.  
  1198.  
  1199.